#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>

#include "pps.h"
#include "url.h"

static int  taskindex = 0;

int pps_event_handler(int index, pps_event event)
{
	unsigned int wparam = event.wparam;

	switch (event.id)
	{
		case EPPS_SERVER_TIMEOUT:
			printf("[pps_callback]: server connecting timeout.\n");
			if (taskindex >= 0)
			{
				ppsvod_stop_item(taskindex);
				ppsvod_remove_item(taskindex);
			}
			break;
		case EPPS_NO_SERVER:
			printf("[pps_callback]: can not find server. \n");
			break;
		case EPPS_SERVER_NO_RESPONSE:
			printf("[pps_callback]: no response from server. \n");
			break;
		case EPPS_SERVER_INVALID:
			printf("[pps_callback]: server invalid. \n");
			break;
		case EPPS_VERSION_LOW:
			printf("[pps_callback]: client version too low. \n");
			break;
		case EPPS_CLIENT_NAME:
			printf("[pps_callback]: client name error.\n");
			break;
		case EPPS_URL_INVALID:
			printf("[pps_callback]: url not found.\n");
			break;
		case EPPS_NO_SERVICE:
			printf("[pps_callback]: service does not exist.\n");
			break;
		case EPPS_OUT_OF_SERVICE:
			printf("[pps_callback]: out of service area.\n");
			break;
		case EPPS_MEDIA_INFO_ERROR:
			printf("[pps_callback]: loading media info error.\n");
			break;
		case EPPS_INDEX_INFO_ERROR:
			printf("[pps_callback]: index info error.\n");
			break;
		case EPPS_NO_INDEX:
			printf("[pps_callback]: no index.\n");
			break;
		case EPPS_NO_MEIDIA:
			printf("[pps_callback]: no media found.\n");
			break;
		case EPPS_MULTI_INSTANCE:
			printf("[pps_callback]: multi instance running.\n");
			break;
		case EPPS_PREPARE_MEDIA_INFO:
			printf("[pps_callback]: preparing media info %d%%.\n", wparam);
			break;
		case EPPS_GETTING_MEDIA_INFO:
			printf("[pps_callback]: requesting media info %d%%.\n", wparam);
			break;
		case EPPS_GETTING_INDEX_INFO:
			printf("[pps_callback]: requesting index info %d%%.\n", wparam);
			break;
		case EPPS_PLAYING:
			printf("[pps_callback]: playing.\n");
			break;
		case EPPS_BUFFERING:
			printf("[pps_callback]: buffering %d%%...\n", wparam);
			break;
		case EPPS_CONNECTING:
			printf("[pps_callback]: connecting to server...\n");
			break;
		case EPPS_MEDIA_READY:
			printf("[pps_callback]: media is ready.\n");
			break;
		case EPPS_PARSING_SERVER:
			printf("[pps_callback]: parsing server info.\n");
			break;
		case EPPS_GET_MEDIA_INFO:
			printf("[pps_callback]: get media info successfully.\n");
			break;
		case EPPS_BUFFERED:
			printf("[pps_callback]: buffing done.\n");
			break;
		case EPPS_PREPARE_MEDIA:
			printf("[pps_callback]: prepare media.\n");
			break;
		case EPPS_STORAGE_ERROR:
			printf("[pps_callback]: access storage failed.\n");
			break;
		case EPPS_DATA_TIMEOUT:
			printf("[pps_callback]: Wait data timeout!\n");
			if (taskindex >= 0)
			{
				ppsvod_stop_item(taskindex);
				ppsvod_remove_item(taskindex);
			}
			break;
		case EPPS_UPDATING:
			printf("[pps_callback]: updating %d%%...\n", wparam);
			break;
		case EPPS_UPDATE_OK:
			printf("[pps_callback]: updating successed\n");
			break;
		case EPPS_UPDATE_FAILED:
			printf("[pps_callback]: updating failed\n");
			if (taskindex >= 0)
			{
				ppsvod_stop_item(taskindex);
				ppsvod_remove_item(taskindex);
			}
			break;
		case EPPS_QUIT:
			printf("[pps_callback]: Quit progress!\n");
			if (taskindex >= 0)
			{
				ppsvod_stop_item(taskindex);
				ppsvod_remove_item(taskindex);
			}
			break;
		default:
			printf("[pps_callback]: unknown event.\n");
			break;
	}
	return 0;
}

int main(int argc, char** argv)
{
	int len;
	char *url, *ptr;
	char gb_url[1024];
	char tvod_url[1024];
	FILE *fpout = NULL;
	ppsvod_iteminfo    *piteminfo;
	int             ret = 0;
	int             filepos = 0;
	char            outbuf[2048];
	//	char            outbuf[64 * 1024];
	struct timeval  block_time;
	unsigned long long pos = 0;
	struct stat stat_;

	printf("------PPS Vod start...\n");
	//again:
	taskindex = 0;
	ret = 0;
	filepos = 0;
	//filepos+=9000;

	if (argc == 2)
	{
		strcat(tvod_url,argv[1]);
		goto start;
	}

#if 1
	if (strncmp(argv[2], "pps://", 6) != 0){
		strcat(tvod_url,argv[2]);

	}
	else{
		url_unescape(argv[2]);
		url = argv[2];
		url += 6;
		len = utf8_to_gb(gb_url, 1024, url);
		if (len < 0){
			printf("convert pps:// to tvod:// error\n");
			return -1;
		}
		ptr = url_escape(gb_url);
		if (ptr == NULL){
			printf("convert pps:// to tvod:// error2\n");
			return -1;
		}

		strcpy(url, ptr);
		pps2tvod(tvod_url, 1023, argv[2], 0);


	}
#endif

start:
	/* initialization */
	if (ppsvod_create("ppstream", "demo", "ppsdemo001", pps_event_handler) < 0)
	{
		printf("------PPS initialization failed!\n");
		return -1;
	}

	if ((fpout = fopen("/tmp/file.out", "a+")) == NULL)
	{
		printf("------Open output file failed\n");
		return -1;
	}
	stat("/tmp/file.out",&stat_);
	filepos = stat_.st_size;
	

	printf("------Adding task...\n");
	/* NOTE: This is just a demo url.
	 * In real world, you should get xml file from ppstream.com, 
	 * retrieve urls from that xml file, then pass it to pps_add_task.
	 */
	//if ((taskindex = ppsvod_add_item("pps://hwhna3gqea6y5udq2aqa.pps/%D6%D0%B9%FA%CA%BD%C0%EB%BB%E9-01.rmvb", 0)) < 0)
	if ((taskindex = ppsvod_add_item(tvod_url,0))<0)
	{
		printf("------Add task failed!\n");
		fclose(fpout);
		return -1;
	}
	int lenth = ppsvod_get_file_length(taskindex);
	printf("----------get file lenth %d\n",lenth);

	if(ppsvod_seek(taskindex,1000)<0){
		printf("----------pps seek error \n");
	}
	else{
		printf("----------pps seek 1000 success\n");
	}
	printf("------Starting task...\n");
	if (ppsvod_play_item(taskindex, NULL) < 0)
	{
		printf("------Can not start task %d!\n", taskindex);
		fclose(fpout);
		ppsvod_remove_item(taskindex);
		return -1;
	}

	/*
	if(ppsvod_seek(taskindex,90000)<0){
		printf("----------pps seek error \n");
	}
	else{
		printf("----------pps seek 90000 success\n");
	}
	*/
	printf("------Start to play...\n");
	while(1)
	{
		if ((piteminfo = ppsvod_get_item_info(taskindex)) == NULL)
		{
			printf("------Can not get task info!\n");
		}
		else
		{
#if 0
			printf("------[index %d]:Filelen:%lld,Downspeed:%d B/s, Upspeed:%d B/s,PeerCount:%d,Progress:%d%%\r", 
					piteminfo->index, 
					piteminfo->file_size, 
					piteminfo->down_speed, 
					piteminfo->up_speed, 
					piteminfo->peer_count, 
					piteminfo->progress);
#else
			pos = (unsigned long long)filepos;
			printf("------[index %d]:Filelen:%u,Downspeed:%d B/s, Upspeed:%d B/s,PeerCount:%d,Progress:%d%%\r", 
					piteminfo->index, 
					piteminfo->file_size, 
					piteminfo->down_speed, 
					piteminfo->up_speed, 
					piteminfo->peer_count, 
					(unsigned int)((pos * 100) / (unsigned long long)piteminfo->file_size));
#endif


			ppsvod_free_item_info(piteminfo);
		}

		/* "block_time.tv_sec = 30" means pps_read_file() will read in block mode,
		 * if no data can be got in 30 seconds, pps_read_file() will return -1.
		 * Set block_time to NULL will cause pps_read_file() block endlessly util data is read.
		 */
		block_time.tv_sec = 40;
		block_time.tv_usec = 0;
		//		printf("------pps reading....\n");
		//		ret = ppsvod_read(taskindex, outbuf, 64 * 1024, filepos, &block_time);
		ret = ppsvod_read(taskindex, outbuf, 2 * 1024, filepos, &block_time);
		if (ret < 0)
		{
			perror("------pps read failed!\n");
			break;
		}
		else if(ret == 0)
		{
			printf("------pps read file done!\n");
			break;
		}

		//		printf("------pps read ok, len:%d....\n", ret);
		/* write data to a temporary file */
		int wret = 0;
		if ((wret = fwrite(outbuf, 1, ret, fpout)) < ret)
		{
			printf("------pps write file failed\n");
		}

		filepos += ret;

		usleep(20000); /* 20ms */
	}
	printf("------pps read finished...\n");
	ppsvod_stop_item(taskindex);
	printf("------pps removing task...\n");
	ppsvod_remove_item(taskindex);
	fclose(fpout);

	printf("------pps uninitianlizing...\n");
	ppsvod_destroy();
	printf("Demo end, exiting...\n");

	return 0;
}
